module ship_txt_mod

  use datetime
  use string
  use container
  use flogger
  use regex
  use params_mod
  use data_translators_utils_mod
  use ship_mod

  implicit none

  private

  public ship_txt_read

contains

  subroutine ship_txt_read(file_path, ships, records)

    character(*), intent(in) :: file_path
    type(hash_table_type), intent(inout) :: ships
    type(linked_list_type), intent(inout) :: records

    type(ship_type), pointer :: ship
    type(ship_record_type), pointer :: record
    type(datetime_type) time
    character(1024) line
    integer ierr
    integer source
    integer year
    integer month
    integer day
    integer hour
    integer minute
    real lat
    real lon
    character(20) site_name
    integer site_type

    real move_dir ! deg
    real move_spd ! m/s
    real p        ! Pa
    real ta       ! degC
    real td       ! degC
    real rh       ! %
    real wd       ! deg
    real ws       ! m/s
    real sst      ! degC
    integer ice
    real ua       ! m/s
    real va       ! m/s
    real sh       ! mg/kg
    real alt      ! m
    
    integer   p_qc
    integer  ta_qc
    integer  td_qc
    integer  rh_qc
    integer  wd_qc
    integer  ws_qc
    integer sst_qc
    integer ice_qc
    integer  ua_qc
    integer  va_qc
    integer  sh_qc
    integer enc_qc
    integer wind_qc ! FIXME: Merge wind_*_qc into one QC mark.
 
    call log_notice('Reading ' // trim(file_path) // ' ...')

    open(10, file=file_path, action='read', form='formatted')
    ! Header line
    read(10, '(A)') line
    do while (.true.)
      read(10, '(A)', iostat=ierr) line
      if (ierr == 0) then
        read(line, *) source,    & ! 1
                      year,      & ! 2
                      month,     & ! 3
                      day,       & ! 4
                      hour,      & ! 5
                      minute,    & ! 6
                      lat,       & ! 7
                      lon,       & ! 8
                      site_name, & ! 9
                      p,         & ! 13
                      ta,        & ! 14
                      sst          ! 19

        call time%init(year=year, month=month, day=day, hour=hour, minute=minute)
        source = merge(int_missing_value, source, is_missing(source, src='cimiss'))
        lat    = merge(real_missing_value, lat, is_missing(lat, src='cimiss'))
        lon    = merge(real_missing_value, lon, is_missing(lon, src='cimiss'))
        p      = merge(real_missing_value, p, is_missing(p, src='cimiss'))
        ta     = merge(real_missing_value, ta, is_missing(ta, src='cimiss'))
        sst    = merge(real_missing_value, sst, is_missing(sst, src='cimiss'))
        ! Create ship and record.
        if (ships%hashed(site_name)) then
          select type (value => ships%value(site_name))
          type is (ship_type)
            ship => value
          end select
        else
          allocate(ship)
          call ship%init(site_name)
          ship%seq_id = ships%size
          call ships%insert(site_name, ship)
        end if
        allocate(record)
        record%seq_id = records%size
        record%ship => ship
        record%time = time
        ! Set record.
        select case (source)
        case (1)
          record%source = 'GTS'
        case (2)
          record%source = 'ICOADS'
        case (3)
          record%source = 'CFSRGDAS'
        case (4)
          record%source = 'CMA BUOY'
        case (5)
          record%source = 'CHN SHIP'
        case (6)
          record%source = 'CMAILAWS'
        case (9)
          record%source = 'MULTISRC'
        end select
        record%lon    = lon
        record%lat    = lat
        record%p      = p
        record%ta     = ta
        record%sst    = sst
        call records%insert(site_name // '@' // time%isoformat(), record)
        call ship%records%insert(trim(to_str(record%seq_id)), record, nodup=.true.)
      else
        exit
      end if
    end do
    close(10)

    call log_notice('Ship size is ' // trim(to_str(ships%size)) // ', record size is ' // trim(to_str(records%size)) // '.')

  end subroutine ship_txt_read

end module ship_txt_mod
